package de.tum.in.eist.poll.server.persistence;

import java.util.ArrayList;
import java.util.Date;

//import org.joda.time.DateTime;
//import org.joda.time.DateTimeZone;

import de.tum.in.eist.poll.shared.*;

public abstract class Database {
	
//	/**
//	 * start of summer semester: April, 1st
//	 */
//	public static final DateTime SS_START = new DateTime(DateTime.now().getYear(), 4, 1, 00, 00);
//	
//	/**
//	 * start of winter semester: October, 1st
//	 */
//	public static final DateTime WS_START = new DateTime(DateTime.now().getYear(), 10, 1, 00, 00);
//	
//	public static final DateTime convertDateToDateTime(java.util.Date date){
//		return new DateTime(date.getYear() + 1900, date.getMonth() + 1, date.getDate(), date.getHours(), date.getMinutes());
//	}
	
	/**
	 * This method checks if email matches with password.
	 * @param email
	 * @param psswd
	 * @return User if email with psswd is valid, else if user does not exist or psswd is invalid method returns null
	 */
	public abstract User validateUser(String email, String psswd);
	
	/**
	 * Should NOT be used.
	 * This method gets all lectures in the database.
	 * @return ArrayList off all lectures in the DB.
	 */
	public abstract ArrayList<Lecture> getAllLectures();
	
	/**
	 * This method gets all today's lectures.
	 * @return ArraList with all lectures of today
	 */
//	public ArrayList<Lecture> getLecturesOfToday(){
//		return getLecturesFromTo(new DateTime(), new DateTime());
//	}
//	
//	/**
//	 * This method returns all lectures of the current week.
//	 * @return ArrayList of all lectures of the current week (Monday - Sunday)
//	 */
//	public ArrayList<Lecture> getLecturesOfThisWeek(){		
//		DateTime start = new DateTime();
//		start = start.minusDays(start.getDayOfWeek() - 1);
//		DateTime end = new DateTime();
//		end = start.plusWeeks(1).minusDays(1);
//		//System.out.println(start + " to " + end);
//		return getLecturesFromTo(start, end);
//	}
//	
//	/**
//	 * This method returns all lectures of the last week.
//	 * @return ArrayList of all lectures of the week before current week (Monday - Sunday)
//	 */
//	public ArrayList<Lecture> getLecturesOfLastWeek(){	
//		DateTime end = new DateTime();
//		end = end.minusDays(end.getDayOfWeek());
//		DateTime start = new DateTime();
//		start = end.minusWeeks(1);
//		//System.out.println(start + " to " + end);
//		return getLecturesFromTo(start, end);
//	}
//	
//	/**
//	 * This methode gets all lectures of the current month.
//	 * @return ArraList of all lectures of the current month.
//	 */
//	public ArrayList<Lecture> getLecturesOfThisMonth(){	
//		DateTime start = new DateTime();
//		start = start.minusDays(start.getDayOfMonth() - 1);
//		DateTime end = new DateTime();
//		end = start.plusMonths(1).minusDays(1);
//		//System.out.println(start + " to " + end);
//		return getLecturesFromTo(start, end);
//	}
//	
//	/**
//	 * This methode gets all lectures of the current semester.
//	 * @return ArraList of all lectures of the current semester.
//	 */
//	public ArrayList<Lecture> getLecturesOfThisSemester(){
//		DateTime start;
//		DateTime end;
//		if(WS_START.getDayOfYear() > DateTime.now().getDayOfYear() && SS_START.getDayOfYear() <= DateTime.now().getDayOfYear()){
//			// summer semester
//			// init start & end point, to ensure that the correct year is chosen SS_START & WS_START is not just copied
//			start = new DateTime(DateTime.now().getYear(), SS_START.getMonthOfYear(), SS_START.getDayOfMonth(), 0, 0);
//			// day BEFORE start of the winter semester
//			end = (new DateTime(DateTime.now().getYear(), WS_START.getMonthOfYear(), WS_START.getDayOfMonth(), 0, 0)).minusDays(1);
//			//System.out.println("summer " + start + " to " + end);
//			return getLecturesFromTo(start, end);
//		}
//		// winter semester (see comments above)
//		start = new DateTime(DateTime.now().getYear(), WS_START.getMonthOfYear(), WS_START.getDayOfMonth(), 0, 0);
//		end = (new DateTime(DateTime.now().getYear() + 1, SS_START.getMonthOfYear(), SS_START.getDayOfMonth(), 0, 0)).minusDays(1);
//		//System.out.println("winter " + start + " to " + end);
//		return getLecturesFromTo(start, end);
//	}
//	
//	/**
//	 * This method gets all lectures between two specific time-stamps (including start and end point)
//	 * @param start
//	 * @param end
//	 * @return ArraList of lectures between start and end
//	 */
//	protected abstract ArrayList<Lecture> getLecturesFromTo(DateTime start, DateTime end);
//	
	/**
	 * This method gets all lectures between two specific time-stamps (including start and end point)
	 * @param start
	 * @param end
	 * @return ArraList of lectures between start and end
	 */
	public abstract ArrayList<Lecture> getLecturesFromTo(Date start, Date end);
	
	/**
	 * This method searches through all lectures and returns those which contain the search term in their topic.
	 * @param searchTerm
	 * @return ArrayList of lectures which match the searchTerm, if no lecture matches an empty ArrayList is returned.
	 */
	protected abstract ArrayList<Lecture> findLecture(String searchTerm);
	
	/**
	 * This method adds one lecture to the DB.
	 * @param user
	 * @param lecture
	 * @return the added lecture, null if user is not permitted to add lectures
	 */
	public abstract Lecture addNewLecture(User user, Lecture lecture);
	
	/**
	 * This method adds several lectures do the DB.
	 * @param user
	 * @param Lectures
	 * @return an ArrayList with the added lectures, null if user is not permitted to add lectures.
	 */
	public abstract ArrayList<Lecture> addNewLectures(User user, ArrayList<Lecture> lectures);
	
	/**
	 * This method checks if user has already rated the lecture.
	 * @param user
	 * @param lecture
	 * @return true if user has already submitted one feedback or is no student
	 */
	public abstract boolean userHasRatedLecture(User user, Lecture lecture);
	
	/**
	 * This method adds one feedback of a user to a lecture and returns the updated lecture, if user has already commited a 
	 * feedback it will be changed.
	 * @param feedback
	 * @param lecture
	 * @return updated lecture, null if no suitable lecture was found
	 */
	public abstract Lecture addFeedbackToLecture(Feedback feedback, Lecture lecture);
	
	/**
	 * This method changes the existing feedback to one lecture, if no feedback exists a new one is added to the lecture.
	 * @param feedback
	 * @param lecture
	 * @return updated lecture
	 */
	public abstract Lecture changeFeedback(Feedback feedback, Lecture lecture);
	
	/**
	 * This method adds lecture to the notification list for all users in the database, except user.
	 * @param lecture
	 */
	protected abstract void addNotification(User user, Lecture lecture);
	
	/**
	 * This method clears all notifications of this user in the database and in the object and returns the cleared object.
	 * @param user
	 * @return
	 */
	public abstract User clearAllNotifications(User user);
	
	/**
	 * This method clears one notification of this user in the database and in the object and returns the cleared object.
	 * @param user
	 * @param lecture
	 * @return
	 */
	public abstract User clearNotification(User user, Lecture lecture);
}
